//
//  C64Memory.m
//  C64
//
//  Created by Antonio "Willy" Malara on 19/04/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "C64Memory.h"

/*
       A000  D000 E000
	   BFFF  DFFF FFFF
	   -----------------
 000 - ram   ram  ram
 001 - ram   char ram
 010 - ram   char kernal
 011 - basic char kernal
 100 - ram   ram  ram
 101 - ram   io   ram
 110 - ram   io   kernal
 111 - basic io   kernal
 
 */

typedef enum {
	_ram,
	_character,
	_basic,
	_io,
	_kernal
} MemoryType;

MemoryType memoryMap[8][3] =
{
	{_ram,   _ram,       _ram   },
	{_ram,   _character, _ram   },
	{_ram,   _character, _kernal},
	{_basic, _character, _kernal},
	{_ram,   _ram,       _ram   },
	{_ram,   _io,        _ram   },
	{_ram,   _io,        _kernal},
	{_basic, _io,        _kernal}
};

#define BASIC_PRESENT     (memoryMap[memory[1] & 0x7][0] == _basic    )
#define CHARACTER_PRESENT (memoryMap[memory[1] & 0x7][1] == _character)
#define IO_PRESENT        (memoryMap[memory[1] & 0x7][1] == _io       )
#define KERNAL_PRESENT    (memoryMap[memory[1] & 0x7][2] == _kernal   )

@implementation C64Memory

- (id)init;
{
	if ((self = [super init]) == nil)
		return nil;
	
	memset(memory, 0, sizeof(memory));

	[[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"basic"     ofType:@"bin"]] getBytes:basic    ];
	[[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"character" ofType:@"bin"]] getBytes:character];
	[[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"kernal"    ofType:@"bin"]] getBytes:kernal   ];
	
	memory[1] = 0x7;
	
	return self;
}

- (unsigned char)byteAtAddress:(unsigned short)address;
{
	if (((address >= 0xA000) && (address <= 0xBFFF)) && BASIC_PRESENT)
		return basic[address - 0xA000];

	if (((address >= 0xD000) && (address <= 0xDFFF)) && CHARACTER_PRESENT)
		return character[address - 0xD000];

	if (((address >= 0xD000) && (address <= 0xDFFF)) && IO_PRESENT);
		// return io;
	
	if ((address >= 0xE000) && KERNAL_PRESENT)
		return kernal[address - 0xE000];
	
	return memory[address];
}

- (void)setByte:(unsigned char)byte atAddress:(unsigned short)address;
{
	if (((address >= 0xD000) && (address <= 0xDFFF)) && IO_PRESENT)
	{
		NSLog(@"WARNING: setting IO address %04X to %02X NOT IMPLEMENTED", address, byte);
		return;
	}
	
	memory[address] = byte;
}

@end
